home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 09 - 1993 / 09.02 Feb 93 / Screen I⁄O Classes / duMainDoc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-29  |  12.6 KB  |  526 lines  |  [TEXT/KAHL]

  1. /****
  2.  * duMainDoc.c
  3.  *
  4.  *    Document methods for a typical application.
  5.  *
  6.  *  Copyright © 1990 Symantec Corporation.  All rights reserved.
  7.  *
  8.  ****/
  9.  
  10. #include "Global.h"
  11. #include "Commands.h"
  12. #include "CApplication.h"
  13. #include "CBartender.h"
  14. #include "CDataFile.h"
  15. #include "CDecorator.h"
  16. #include "CDesktop.h"
  17. #include "CError.h"
  18. #include "CPanorama.h"
  19. #include "CScrollPane.h"
  20. #include "duMainDoc.h"
  21. #include "duMainPane.h"
  22. #include "TBUtilities.h"
  23. #include "CWindow.h"
  24. #include <Packages.h>
  25.  
  26. #define    WINDStarter        500        /* Resource ID for WIND template */
  27.  
  28. extern    CApplication *gApplication;    /* The application */
  29. extern    CBartender    *gBartender;    /* The menu handling object */
  30. extern    CDecorator    *gDecorator;    /* Window dressing object    */
  31. extern    CDesktop    *gDesktop;        /* The enclosure for all windows */
  32. extern    CBureaucrat    *gGopher;        /* The current boss in the chain of command */
  33. extern    OSType        gSignature;        /* The application's signature */
  34. extern    CError        *gError;        /* The global error handler */
  35.  
  36. /***
  37.  * IduMainDoc
  38.  *
  39.  *    This is your document's initialization method.
  40.  *    If your document has its own instance variables, initialize
  41.  *    them here.
  42.  *
  43.  *    The least you need to do is invoke the default method.
  44.  *
  45.  ***/
  46.  
  47.  
  48. void duMainDoc::IduMainDoc(CApplication *aSupervisor, Boolean printable)
  49.  
  50. {
  51.     CDocument::IDocument(aSupervisor, printable);
  52. }
  53.  
  54.  
  55. /***
  56.  * Dispose
  57.  *
  58.  *    This is your document's destruction method.
  59.  *    If you allocated memory in your initialization method
  60.  *    or opened temporary files, this is the place to release them.
  61.  *
  62.  *    Be sure to call the default method!
  63.  *
  64.  ***/
  65.  
  66. void duMainDoc::Dispose()
  67.  
  68. {
  69.     inherited::Dispose();
  70. }
  71.  
  72.  
  73. /***
  74.  * DoCommand
  75.  *
  76.  *    This is the heart of your document.
  77.  *    In this method, you handle all the commands your document
  78.  *    deals with.
  79.  *
  80.  *    Be sure to call the default method to handle the standard
  81.  *    document commands: cmdClose, cmdSave, cmdSaveAs, cmdRevert,
  82.  *    cmdPageSetup, cmdPrint, and cmdUndo. To change the way these
  83.  *    commands are handled, override the appropriate methods instead
  84.  *    of handling them here.
  85.  *
  86.  ***/
  87.  
  88. void duMainDoc::DoCommand(long theCommand)
  89.  
  90. {
  91.     switch (theCommand) {
  92.  
  93.         /* your document commands here */
  94.     
  95.         default:    inherited::DoCommand(theCommand);
  96.                     break;
  97.     }
  98. }
  99.  
  100.  
  101. /***
  102.  * UpdateMenus
  103.  *
  104.  *  In this method you can enable menu commands that apply when
  105.  *  your document is active.
  106.  *
  107.  *  Be sure to call the inherited method to get the default behavior.
  108.  *  The inherited method enables these commands: cmdClose, cmdSaveAs,
  109.  *  cmdSave, cmdRevert, cmdPageSetup, cmdPrint, cmdUndo.
  110.  *
  111. ***/
  112.  
  113.  void duMainDoc::UpdateMenus()
  114.  
  115.  {
  116.   inherited::UpdateMenus();
  117.  
  118.     /* Enable your menu commands here (enable each one with a call to   
  119.        gBartender->EnableCmd(command_number)).  
  120.     */                      
  121.  
  122.  }
  123.  
  124.  
  125. /***
  126.  * NewFile
  127.  *
  128.  *    When the user chooses New from the File menu, the CreateDocument()
  129.  *    method in your Application class will send a newly created document
  130.  *    this message. This method needs to create a new window, ready to
  131.  *    work on a new document.
  132.  *
  133.  *    Since this method and the OpenFile() method share the code for creating
  134.  *    the window, you should use an auxiliary window-building method.
  135.  *
  136.  ***/
  137. void duMainDoc::NewFile(void)
  138.  
  139. {    
  140.     Str255  wTitle;     /* Window title string.         */
  141.     short   wCount;     /* Index number of new window.  */
  142.     Str255  wNumber;    /* Index number as a string.    */
  143.     
  144.         /**
  145.          **    BuildWindow() is the method that
  146.          **    does the work of creating a window.
  147.          ** Its parameter should be the data that
  148.          **    you want to display in the window.
  149.          **    Since this is a new window, there's nothing
  150.          **    to display.
  151.          **
  152.          **/
  153.  
  154.     BuildWindow(NULL);
  155.     
  156.         /**
  157.          ** Append an index number to the
  158.          ** default name of the window.
  159.          **/
  160.          
  161.     itsWindow->GetTitle(wTitle);
  162.     wCount = gDecorator->GetWCount();
  163.     NumToString(wCount, wNumber);
  164.     ConcatPStrings(wTitle, (StringPtr) "\p ");
  165.     ConcatPStrings(wTitle, wNumber);
  166.     itsWindow->SetTitle(wTitle);
  167.  
  168.         /**
  169.          **    Send the window a Select() message to make
  170.          **    it the active window.
  171.          **/
  172.     
  173.     itsWindow->Select();
  174. }
  175.  
  176.  
  177. /***
  178.  * OpenFile
  179.  *
  180.  *    When the user chooses Open… from the File menu, the OpenDocument()
  181.  *    method in your Application class will let the user choose a file
  182.  *    and then send a newly created document this message. The information
  183.  *    about the file is in the SFReply record.
  184.  *
  185.  *    In this method, you need to open the file and display its contents
  186.  *    in a window. This method uses the auxiliary window-building method.
  187.  *
  188.  ***/
  189.  
  190. void duMainDoc::OpenFile(SFReply *macSFReply)
  191.  
  192. {
  193.     CDataFile    *theFile;
  194.     Handle        theData = NULL;
  195.     Str63        theName;
  196.     OSErr        theError;
  197.     
  198.     TRY
  199.     {
  200.     
  201.             /**
  202.              ** Create a file and send it a SFSpecify()
  203.              **    message to set up the name, volume, and
  204.              **    directory.
  205.              **
  206.              **/
  207.     
  208.         theFile = new(CDataFile);
  209.         theFile->IDataFile();
  210.         theFile->SFSpecify(macSFReply);
  211.         
  212.             /**
  213.              **    Be sure to set the instance variable
  214.              **    so other methods can use the file if they
  215.              **    need to. This is especially important if
  216.              **    you leave the file open in this method.
  217.              **    If you close the file after reading it, you
  218.              **    should be sure to set itsFile to NULL.
  219.              **
  220.              **/
  221.     
  222.         itsFile = theFile;
  223.     
  224.             /**
  225.              **    Send the file an Open() message to
  226.              **    open it. You can use the ReadSome() or
  227.              **    ReadAll() methods to get the contents of the file.
  228.              **
  229.              **/
  230.     
  231.         theFile->Open(fsRdWrPerm);
  232.         
  233.             /**
  234.              **    Make sure that the memory request to read
  235.              **    the data from the file doesn't use up any
  236.              **    of our rainy day fund and that the GrowMemory()
  237.              **    method (in the application) knows that it's OK
  238.              **    if we couldn't get enough memory.
  239.              **
  240.              **/
  241.     
  242.     
  243.         theData = theFile->ReadAll();     /* ReadAll() creates the handle */
  244.         
  245.      
  246.         
  247.         
  248.         BuildWindow(theData);
  249.     
  250.             /**
  251.              **    In your application, you'll probably store
  252.              **    the data in some form as an instance variable
  253.              **    in your document class. For this example, there's
  254.              **    no need to save it, so we'll get rid of it.
  255.              **
  256.              **/
  257.     
  258.         DisposHandle(theData);
  259.         theData = NULL;
  260.     
  261.             /**
  262.              **    In this implementation, we leave the file
  263.              **    open. You might want to close it after
  264.              **    you've read in all the data.
  265.              **
  266.              **/
  267.     
  268.         itsFile->GetName(theName);
  269.         itsWindow->SetTitle(theName);
  270.         itsWindow->Select();            /* Don't forget to make the window active */
  271.     }
  272.     
  273.     CATCH
  274.     {
  275.         /*
  276.          * This exception handler will be executed if an exception occurs
  277.          * anywhere within the scope of the TRY block above.
  278.          * You should perform any cleanup of things that won't be needed
  279.          * since the document could not be opened. By convention,
  280.          * the creator of an object is responsible for sending it
  281.          * the Dispose message. This means that we should only dispose
  282.          * of things that would not be taken care of in Dispose.
  283.          * In this case, we just make sure that the Handle theData
  284.          * has been disposed of. The exception will propagate up to
  285.          * CApplications's exception handler, which handles displaying
  286.          * an error alert.
  287.          */
  288.          
  289.          if (theData) DisposHandle( theData);
  290.          
  291.     }
  292.     ENDTRY;
  293. }
  294.  
  295.  
  296.  
  297. /***
  298.  * BuildWindow
  299.  *
  300.  *    This is the auxiliary window-building method that the
  301.  *    NewFile() and OpenFile() methods use to create a window.
  302.  *
  303.  *    In this implementation, the argument is the data to display.
  304.  *
  305.  ***/
  306.  
  307. void duMainDoc::BuildWindow (Handle theData)
  308.  
  309. {
  310.     CScrollPane        *theScrollPane;
  311.     duMainPane    *theMainPane;
  312.  
  313.         /**
  314.          **    First create the window and initialize
  315.          **    it. The first argument is the resource ID
  316.          **    of the window. The second argument specifies
  317.          **    whether the window is a floating window.
  318.          **    The third argument is the window's enclosure; it
  319.          **    should always be gDesktop. The last argument is
  320.          **    the window's supervisor in the Chain of Command;
  321.          **    it should always be the Document object.
  322.          **
  323.          **/
  324.  
  325.     itsWindow = new(CWindow);
  326.     itsWindow->IWindow(WINDStarter, FALSE, gDesktop, this);
  327.     
  328.         /**
  329.          **    After you create the window, you can use the
  330.          **    SetSizeRect() message to set the window’s maximum
  331.          **    and minimum size. Be sure to set the max & min
  332.          **    BEFORE you send a PlaceNewWindow() message to the
  333.          **    decorator.
  334.          **
  335.          ** The default minimum is 100 by 100 pixels. The
  336.          **    default maximum is the bounds of GrayRgn() (The
  337.          **    entire display area on all screens.)
  338.          **
  339.          ** We'll use the defaults.
  340.          **
  341.          **/
  342.     
  343.         /**
  344.          ** Our window will contain a ScrollPane,
  345.          ** which in turn will contain a Panorama.
  346.          ** Now, let's create the ScrollPane.
  347.          **/
  348.  
  349.     theScrollPane = new(CScrollPane);
  350.     
  351.         /**
  352.          **    You can initialize a scroll pane two ways:
  353.          **        1. You can specify all the values
  354.          **           right in your code, like this.
  355.          **        2. You can create a ScPn resource and
  356.          **           initialize the pane from the information
  357.          **           in the resource.
  358.          **
  359.          **/
  360.  
  361.     theScrollPane->IScrollPane(itsWindow, this, 10, 10, 0, 0,
  362.                                 sizELASTIC, sizELASTIC,
  363.                                 TRUE, TRUE, TRUE);
  364.  
  365.         /**
  366.          **    The FitToEnclFrame() method makes the
  367.          **    scroll pane be as large as its enclosure.
  368.          **    In this case, the enclosure is the window,
  369.          **    so the scroll pane will take up the entire
  370.          **    window.
  371.          **
  372.          **/
  373.  
  374.     theScrollPane->FitToEnclFrame(TRUE, TRUE);
  375.  
  376.  
  377.         /**
  378.          **    itsMainPane is the document's focus
  379.          **    of attention. Some of the standard
  380.          **    classes (particularly CPrinter) rely
  381.          **    on itsMainPane pointing to the main
  382.          **    pane of your window.
  383.          **
  384.          **    itsGopher specifies which object
  385.          ** should become the gopher when the document
  386.          ** becomes active. By default
  387.          **    the document becomes the gopher. It’s
  388.          **    likely that your main pane handles commands
  389.          **    so you’ll almost always want to set itsGopher
  390.          **    to point to the same object as itsMainPane.
  391.          **
  392.          **    Note that the main pane is the
  393.          **    panorama in the scroll pane and not
  394.          **    the scroll pane itself.
  395.          **
  396.          **/
  397.  
  398.     theMainPane = new(duMainPane);
  399.     theMainPane->IduMainPane(theScrollPane, this, 0, 0, 0, 0, sizELASTIC, sizELASTIC);
  400.     itsMainPane = theMainPane;
  401.     itsGopher = theMainPane;
  402.     
  403.         /**    The FitToEnclosure() method makes the pane
  404.          **    fit inside the enclosure. The inside (or
  405.          **    interior) of a scroll pane is defined as
  406.          **    the area inside the scroll bars.
  407.          **/
  408.  
  409.     theMainPane->FitToEnclosure(TRUE, TRUE);
  410.  
  411.         /**
  412.          **    Send the scroll pane an InstallPanorama()
  413.          ** message to associate the panorama with 
  414.          ** the scroll pane.
  415.          **
  416.          **/
  417.  
  418.     theScrollPane->InstallPanorama(theMainPane);
  419.     
  420.         /**
  421.          **    The Decorator is a global object that takes care
  422.          **    of placing and sizing windows on the screen.
  423.          **    You don't have to use it.
  424.          **
  425.          **/
  426.  
  427.     gDecorator->PlaceNewWindow(itsWindow);
  428. }
  429.  
  430.  
  431. /***
  432.  * DoSave
  433.  *
  434.  *    This method handles what happens when the user chooses Save from the
  435.  *    File menu. This method should return TRUE if the file save was successful.
  436.  *    If there is no file associated with the document, you should send a
  437.  *    DoSaveFileAs() message.
  438.  *
  439.  ***/
  440.  
  441. Boolean duMainDoc::DoSave(void)
  442.  
  443. {
  444.         /**
  445.          **    If you closed your file in your NewFile() method,
  446.          **    you'll need a different way than this to determine
  447.          **    if there's a file associated with your document.
  448.          **
  449.          **/
  450.  
  451.     if (itsFile == NULL)
  452.         return(DoSaveFileAs());
  453.     else {
  454.             
  455.         /**
  456.          **    In your application, this is where you'd
  457.          **    write out your file. if you left it open,
  458.          **    send the WriteSome() or WriteAll() mesages
  459.          **    to itsFile.
  460.          **
  461.          **/
  462.             
  463.         dirty = FALSE;                    /* Document is no longer dirty        */
  464.         gBartender->DisableCmd(cmdSave);
  465.         return(TRUE);                    /* Save was successful                */
  466.     }
  467. }
  468.  
  469.  
  470. /***
  471.  * DoSaveAs
  472.  *
  473.  *    This method handles what happens when the user chooses Save As… from
  474.  *    File menu. The default DoCommand() method for documents sends a DoSaveFileAs()
  475.  *    message which displays a standard put file dialog and sends this message.
  476.  *    The SFReply record contains all the information about the file you're about
  477.  *    to create.
  478.  *
  479.  ***/
  480.  
  481. Boolean duMainDoc::DoSaveAs(SFReply *macSFReply)
  482.  
  483. {
  484.         /**
  485.          **    If there's a file associated with this document
  486.          **    already, close it. The Dispose() method for files
  487.          **    sends a Close() message to the file before releasing
  488.          **    its memory.
  489.          **
  490.          **/
  491.          
  492.     if (itsFile != NULL)
  493.         itsFile->Dispose();
  494.  
  495.  
  496.         /**
  497.          **    Create a new file, and then save it normally.
  498.          **
  499.          **/
  500.  
  501.     itsFile = new(CDataFile);
  502.     ((CDataFile *)itsFile)->IDataFile();
  503.     itsFile->SFSpecify(macSFReply);
  504.     itsFile->CreateNew(gSignature, 'TEXT');
  505.     itsFile->Open(fsRdWrPerm);
  506.     
  507.     itsWindow->SetTitle(macSFReply->fName);
  508.  
  509.     return( DoSave() );
  510. }
  511.  
  512.  
  513. /***
  514.  * DoRevert
  515.  *
  516.  *    If your application supports the Revert command, this method
  517.  *    should close the current file (without writing anything out)
  518.  *    and read the last saved version of the file.
  519.  *
  520.  ***/
  521.  
  522. void duMainDoc::DoRevert(void)
  523.  
  524. {
  525. }
  526.